#include <rclcpp/rclcpp.hpp>
#include "performance_test_base.h"

namespace trace_api = opentelemetry::trace;
namespace nostd = opentelemetry::nostd;

class MemoryStressTestNode : public rclcpp::Node {
public:
    MemoryStressTestNode() : Node("memory_stress_test_node") {
        // Initialize OpenTelemetry
        PerformanceTestBase::InitTracer();
        tracer_ = trace_api::Provider::GetTracerProvider()->GetTracer("memory-stress-test");
        
        RCLCPP_INFO(this->get_logger(), "Memory Stress Test started");
        RCLCPP_INFO(this->get_logger(), "Testing memory stress with many spans...");
        
        runMemoryStressTest();
        
        RCLCPP_INFO(this->get_logger(), "Memory stress test completed!");
    }

private:
    void runMemoryStressTest() {
        RCLCPP_INFO(this->get_logger(), "Running memory stress test...");
        
        PerformanceStats stats;
        stats.reset();
        
        stats.memory_before_kb = PerformanceTestBase::getCurrentMemoryKB();
        auto cpu_before = PerformanceTestBase::getCurrentCPUTime();
        stats.cpu_time_user_before = cpu_before.first;
        stats.cpu_time_system_before = cpu_before.second;
        
        const size_t iterations = 5000;
        std::vector<nostd::shared_ptr<trace_api::Span>> span_pool;
        
        auto start_time = std::chrono::high_resolution_clock::now();
        
        // Create many spans and keep them alive
        for (size_t i = 0; i < iterations; ++i) {
            auto span = tracer_->StartSpan("memory_stress_span", {
                {"iteration", static_cast<int64_t>(i)},
                {"memory_test", true}
            });
            
            span->SetAttribute("large_data", std::string(1000, 'A' + (i % 26)));
            span_pool.push_back(span);
            
            if (i % 1000 == 0) {
                // End some spans to simulate real usage
                for (size_t j = 0; j < 100 && !span_pool.empty(); ++j) {
                    span_pool.back()->End();
                    span_pool.pop_back();
                }
            }
        }
        
        // End remaining spans
        for (auto& span : span_pool) {
            span->End();
        }
        
        auto end_time = std::chrono::high_resolution_clock::now();
        stats.total_time = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time);
        stats.operation_count = iterations;
        
        stats.memory_after_kb = PerformanceTestBase::getCurrentMemoryKB();
        auto cpu_after = PerformanceTestBase::getCurrentCPUTime();
        stats.cpu_time_user_after = cpu_after.first;
        stats.cpu_time_system_after = cpu_after.second;
        
        stats.calculateAverages();
        PerformanceTestBase::printStats("Memory Stress Test", stats);
    }

    nostd::shared_ptr<trace_api::Tracer> tracer_;
};

int main(int argc, char* argv[]) {
    rclcpp::init(argc, argv);
    
    auto node = std::make_shared<MemoryStressTestNode>();
    
    RCLCPP_INFO(node->get_logger(), "Starting Memory Stress Performance Test...");
    RCLCPP_INFO(node->get_logger(), "This will test OpenTelemetry's memory usage under stress");
    
    rclcpp::spin(node);
    rclcpp::shutdown();
    
    return 0;
}
